package controller

import (
	. "gddgame.cc/galaxy/common/dsl/game/achievement"
	. "gddgame.cc/galaxy/common/dsl/game/ad"
	. "gddgame.cc/galaxy/common/dsl/game/reward"
	. "gddgame.cc/galaxy/common/dsl/game/user"
	"gddgame.cc/galaxy/project/maze/maze/model"
	"gddgame.cc/galaxy/utils"
	"gddgame.cc/galaxy/utils/orm"

	"gddgame.cc/galaxy/utils/def"
)

func GetUserPublicInfo(context def.Context, user *model.User, language string) (*model.GameOtherUserExtend, error) {
	// 账号信息，等级信息，属性信息
	data := &model.GameOtherUserExtend{
		SingleStar:  user.SingleStar,
		SingleScore: user.SingleScore,
		OnlineScore: user.OnlineScore,
		Entity:      user.Entity,
	}
	return data, nil
}

func GetUserDetailInfo(context def.Context, user *model.User, language string) (*model.GameUserExtend, error) {
	if err := Center.GetUserStats(context, user, Center.StatData); err != nil {
		return nil, err
	}
	// 账号信息，等级信息，装备信息，道具信息，属性值
	data := &model.GameUserExtend{
		SingleStar:  user.SingleStar,
		SingleScore: user.SingleScore,
		SingleRank:  0,
		OnlineScore: user.OnlineScore,
		OnlineRank:  0,
		Gold:        user.Gold,
		Entity:      user.Entity,
	}
	if user.SingleScore > 0 {
		data.SingleRank, _ = Env.NumberLeaderboard(Env.ID(), user.OpenId, model.SingleLeaderboard)
	}
	if user.OnlineScore > 0 {
		data.OnlineRank, _ = Env.NumberLeaderboard(Env.ID(), user.OpenId, model.OnlineLeaderboard)
	}
	if user.Achievements == nil {
		user.Achievements = map[int]*UserAchievement{}
	}

	data.Achievements = Center.FullAchievement(user.Achievements, user.StatInfo, data.Achievements, -1)
	return data, nil
}

func UpdateAchievementSingle(context def.Context, user *model.User, achievementId int, data map[string]interface{}) error {
	if achievementId == 0 {
		return nil
	}
	if user.Achievements == nil {
		user.Achievements = make(map[int]*UserAchievement)
	}
	if ok, err := Center.ValidAchievement(user.Achievements, user.StatInfo, user.OpenId, achievementId); err != nil {
		return err
	} else if !ok {
		return nil
	}
	message, err := SendAchievementMessage(context, user.Id, achievementId, Center.Achievements[achievementId].Extend.(*Reward))
	if err != nil {
		return err
	}
	// 设置extend为messageid，表明未领取奖励
	user.Achievements[achievementId].Extend = message.Id
	_ = Center.ChangeAchievement(user.Achievements, data)
	return nil
}

func UpdateAchievements(context def.Context, user *model.User, data map[string]interface{}) error {
	if user.Achievements == nil {
		user.Achievements = make(map[int]*UserAchievement)
	}
	for _, achievement := range Center.Achievements {
		if _, ok := user.Achievements[achievement.Id]; ok {
			continue
		}
		if ok, err := Center.ValidAchievement(user.Achievements, user.StatInfo, user.OpenId, achievement.Id); err != nil {
			return err
		} else if !ok {
			continue
		}
		message, err := SendAchievementMessage(context, user.Id, achievement.Id, Center.Achievements[achievement.Id].Extend.(*Reward))
		if err != nil {
			return err
		}
		// 设置extend为messageid，表明未领取奖励
		user.Achievements[achievement.Id].Extend = message.Id
	}
	_ = Center.ChangeAchievement(user.Achievements, data)
	return nil
}

func ReceiveReward(context def.Context, user *model.User, reward *GoldReward, data map[string]interface{}) error {
	if reward.Gold > 0 {
		data["gold"] = &orm.UpdateOperate{Operate: "+", Value: reward.Gold}
		if err := user.ChangeStats(context, model.GoldStat, int32(reward.Gold), false); err != nil {
			return err
		}
		if err := UpdateAchievementSingle(context, user, model.GoldAchievement, data); err != nil {
			return err
		}
	}
	return nil
}

func ReceiveRewardMessage(context def.Context, user *model.User, messageId int) (*GoldReward, error) {
	message, err := Center.GetMessage(user.Id, messageId)
	if err != nil {
		return nil, err
	}
	_ = Center.ReadMessage(user.Id, messageId)
	data := map[string]interface{}{}
	gold := GoldRewardFromReward(&message.Reward)
	if t, err := NextAd(Env, user.OpenId, model.SingleAdPlane); err == nil {
		if t.Ok() {
			_ = UpdateAd(Env, user.OpenId, t)
			gold.Gold = gold.Gold * 3
		}
	}
	switch message.Type {
	case model.AchievementMessage:
		// 重置extend为0，表明已领取奖励
		user.Achievements[utils.ToInt(message.TargetId)].Extend = 0
		data["achievement"] = user.Achievements
	case model.SingleMessage:
	case model.OnlineMessage:
	}
	if err := Center.GetUserStats(context, user, Center.StatData); err != nil {
		return nil, err
	}
	if err := ReceiveReward(context, user, gold, data); err != nil {
		return nil, err
	}
	if err := Center.UpdateUser(user, data); err != nil {
		return nil, err
	}
	return gold, nil
}

func SendShareMessage(context def.Context, userId int, target string, nickName string) (*UserMessage, error) {
	message := &UserMessage{
		UserId:   userId,
		Type:     model.ShareMessage,
		TargetId: target,
		Status:   false,
		Content: map[string]string{
			"nick_name": nickName,
		},
		Reward: model.DefaultShareReward,
	}
	if err := Center.SendMessage(message); err != nil {
		return nil, err
	}
	return message, nil
}

func SendAchievementMessage(context def.Context, userId int, achievementId int, reward *Reward) (*UserMessage, error) {
	message := &UserMessage{
		UserId:   userId,
		Type:     model.AchievementMessage,
		TargetId: utils.ToString(achievementId),
		Status:   false,
		Content:  map[string]string{},
		Reward:   *reward,
	}
	if err := Center.SendMessage(message); err != nil {
		return nil, err
	}
	return message, nil
}

func SendSingleMessage(context def.Context, userId int, singleKey string, reward *Reward) (*UserMessage, error) {
	message := &UserMessage{
		UserId:   userId,
		Type:     model.SingleMessage,
		TargetId: singleKey,
		Status:   false,
		Content:  map[string]string{},
		Reward:   *reward,
	}
	if err := Center.SendMessage(message); err != nil {
		return nil, err
	}
	return message, nil
}

func SendOnlineMessage(context def.Context, userId int, mapId string, reward *Reward) (*UserMessage, error) {
	message := &UserMessage{
		UserId:   userId,
		Type:     model.OnlineMessage,
		TargetId: mapId,
		Status:   false,
		Content:  map[string]string{},
		Reward:   *reward,
	}
	if err := Center.SendMessage(message); err != nil {
		return nil, err
	}
	return message, nil
}
